package com.twang.stock.service;

import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.twang.stock.common.http.HtmlTools;
import com.twang.stock.config.StockMsgSender;
import com.twang.stock.dto.EmailMessage;
import com.twang.stock.dto.TenXunStock;
import com.twang.stock.entity.CompanyStock;
import com.twang.stock.entity.CompanyStockMinutes;
import com.twang.stock.entity.User;
import com.twang.stock.mapper.CompanyStockMapper;
import com.twang.stock.mapper.CompanyStockMinutesMapper;
import com.twang.stock.mapper.UserMapper;
import com.twang.stock.redis.RedisUtil;
import com.twang.stock.service.jinyan.CommonService;
import com.twang.stock.email.SendmailService;
import com.twang.stock.utils.date.DateUtils;
import com.twang.stock.utils.date.HolidayCopy;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;

@Service
@Slf4j
public class ZuoTiService {

    @Autowired
    private CommonService commonService;

    @Resource
    private UserMapper userMapper;

    @Resource
    private CompanyStockMapper companyStockMapper;

    @Resource
    private CompanyStockMinutesMapper companyStockMinutesMapper;

    @Autowired
    private ZhangTingBanService zhangTingBanService;


    @Resource
    private CompanyStockMinutesService companyStockMinutesService;

    @Resource
    private StockMsgSender stockMsgSender;

    @Resource
    private SendmailService sendmailService;
    @Resource
    private RedisUtil redisUtil;

    public volatile  static List<String> dates= Lists.newArrayList();


    public void 做T预警() {
        String key="";
        List<String> ids = Arrays.asList(commonService.getValue("warn_zuoT_ID").toString().split(","));
        for (String id : ids) {
            User user = userMapper.selectByPrimaryKey(id);
            CompanyStock companyStock = new CompanyStock();
            companyStock.setUserId(user.getId().intValue());
            List<CompanyStock> companyStockList=  companyStockMapper.select(companyStock);
            StringBuffer buffer = new StringBuffer("");
            if (null != user && CollectionUtils.isNotEmpty(companyStockList)) {
                log.info(">>>>>>>>>>>> start 做T预警 user id ={} email={} ",id,user.getEmail());
                //adminFuPan(user.getEmail());
                for (CompanyStock companyStock1 : companyStockList) {
                    if(companyStock1.getCompanyCode().startsWith("6")){
                        buffer.append("sh");
                    }else{
                        buffer.append("sz");
                    }
                    buffer.append(companyStock1.getCompanyCode()).append(",");
                }
                key=buffer.toString().replace("s_s_","s_").replace(",s_,",",");
                判断是否触发预警(user,key);
            }
        }
    }

    private void 判断是否触发预警(User user,String key) {
        String vipKey="zuo_ti_vip";
        List<TenXunStock> tenXunStocks = HtmlTools.httpGet(key);
        List<String> dates = companyStockMinutesMapper.queryDates();
        Integer number = 0;
        List<String> zuoTiVip = Arrays.asList(commonService.getValue(vipKey).toString().split(","));
        for (TenXunStock p : tenXunStocks) {
            // tenXunStocks.stream().forEach(p -> {
            number++;
            //vip-付费，普通
            if (zuoTiVip.contains(user.getId().toString()) || number < 5) {
                String warn_key_stock=new StringBuffer("warn_key_stock_").append(user.getEmail()).append("_").append(p.getStockCode()).append("_").append(HolidayCopy.getToday()).toString();
                if(null==redisUtil.get(warn_key_stock)){
                    extractedForZuoT(user, dates, p);
                }
            }
            if (number >= 5 && !zuoTiVip.contains(user.getId().toString())) {
                if ("8,9".contains(user.getId().toString())) {
                    //忽略
                } else {
                    String warnKeyvipKey = new StringBuffer(vipKey).append("_").append(user.getId()).append("_").append(HolidayCopy.getToday()).toString();
                    if (null == redisUtil.get(warnKeyvipKey)) {
                        if (null != user.getEmail()) {
                            log.info(">>>>>>>>> send email={}", user.getEmail());
                            String messages = new StringBuffer("预警超过限制:很抱歉，由于资源有限的原因，您的预警最多设置5个监控").toString();
                            try {
                                EmailMessage emailMessage = new EmailMessage();
                                emailMessage.setCode(p.getStockCode());
                                emailMessage.setName(p.getStockName());
                                emailMessage.setEmail(user.getEmail());
                                emailMessage.setMessage(messages);
                                stockMsgSender.sendEmailMessage(JSONObject.toJSONString(emailMessage));
                            } catch (Exception e) {
                                //sendmailService.sendMailWithByZuoT(messages, p.getStockName(), p.getStockCode(), user.getEmail());
                            }
                            redisUtil.set(warnKeyvipKey, user.getEmail(),60*10);
                        }
                    }
                }
            }
        }
            // });
    }

    /**
     *
     * @param user
     * @param dates
     * @param p
     */
    private void extractedForZuoT(User user, List<String> dates, TenXunStock p) {
        if (51 == p.getExchange()) {
            p.setStockCode("sz" + p.getStockCode());
        } else {
            p.setStockCode("sh" + p.getStockCode());
        }

        BigDecimal hisDayTradeVol = BigDecimal.ZERO;
        hisDayTradeVol = getHistoryVol(user, p, dates, hisDayTradeVol);
        //更新分钟量能
        Example example = new Example(CompanyStockMinutes.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("date", HolidayCopy.getRealToday());
        criteria.andEqualTo("companyCode", p.getStockCode());
        example.orderBy("id").desc();
        List<CompanyStockMinutes> list = companyStockMinutesMapper.selectByExample(example);
        if (org.apache.commons.collections.CollectionUtils.isNotEmpty(list)) {
            CompanyStockMinutes last = list.get(0);
            if (p.getStockCode().startsWith("sh688")) {
                p.setTradingVolume(p.getTradingVolume().divide(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP));
            }
            BigDecimal newVole = p.getTradingVolume().subtract(last.getTradeVol());
            if (newVole.compareTo(hisDayTradeVol) > 0) {
                log.info(">>>>>>>>>>>> start 判断是否触发预警 触发 user id={} email={} stock={} 当前vol={} hisVol={} ", user.getId(), user.getEmail(), p.getStockName(), newVole, hisDayTradeVol);
                //触发了
                p.setTFlags(1);
                sendEmail(user.getEmail(), p);
            } else {
                log.info(">>>>>>>>>>>> start 判断是否触发预警 未触发 user id={} email={} stock={} 当前vol={} hisVol={} ", user.getId(), user.getEmail(), p.getStockName(), newVole, hisDayTradeVol);
                p.setTFlags(0);
            }
        }
        p.setTurnover(p.getTradingVolume().divide(new BigDecimal(10000)).setScale(2, BigDecimal.ROUND_HALF_UP));
    }


    /**
     * 判断量能是否触发
     * @param p
     */
    private void extractedZuoTi(TenXunStock p) {
        if (51 == p.getExchange()) {
            p.setStockCode("sz" + p.getStockCode());
        } else {
            p.setStockCode("sh" + p.getStockCode());
        }

        //历史平均量能
        BigDecimal historyTradeVol = extractedZuoTiGetHistoryVol(p);

        String lastMinutesKey = new StringBuffer("lastMinutesKey:").append(p.getStockCode()).append(":").append(HolidayCopy.getHHmmss()).toString();
        Object lastMinutesKeyObject = redisUtil.get(lastMinutesKey);
        BigDecimal lastMinutesTradeVol;
        if (null == lastMinutesKeyObject) {
            //ZT 更新分钟量能
            lastMinutesTradeVol = companyStockMinutesMapper.queryLastStockMinutesVol(p.getStockCode(), HolidayCopy.getRealToday());
            //缓存最新的分时数据，方便下一分钟做T得到的
            redisUtil.set(lastMinutesKey, p.getTradingVolume(), 60);
            log.info(">>>>>>>>> 缓存最新的分时数据， lastMinutesKey={} ", lastMinutesKey);
        } else {
            lastMinutesTradeVol = new BigDecimal(lastMinutesKeyObject.toString());
            log.info(">>>>>>>>> 通过缓存获取到最新的数据， lastMinutesKey={}  lastMinutesTradeVol={} ", lastMinutesKey, lastMinutesTradeVol);
        }

        if (null != lastMinutesTradeVol) {
            BigDecimal newVole = p.getTradingVolume().subtract(lastMinutesTradeVol);
            if (newVole.compareTo(historyTradeVol) > 0) {
                //触发了
                p.setTFlags(1);
            } else {
                p.setTFlags(0);
            }

        }
        p.setTurnover(p.getTradingVolume().divide(new BigDecimal(10000)).setScale(2, BigDecimal.ROUND_HALF_UP));
    }
    private BigDecimal extractedZuoTiGetHistoryVol( TenXunStock p) {
        BigDecimal hisDayTradeVol=BigDecimal.ZERO;
        if(org.apache.commons.collections.CollectionUtils.isEmpty(dates)){
            dates.addAll(companyStockMinutesMapper.queryDates());
        }
        /** 昨天 */
        int i = 2;
        int j = 0;
        String key_avg_volume=new StringBuffer("key_avg_volume").append("_").append(p.getStockCode()).append("_").append(HolidayCopy.getToday()).toString();
        Object object=redisUtil.get(key_avg_volume);
        if(null==object) {
            try{
                for (String date : dates) {
                    int size = dates.size() - i;
                    try {
                        date = dates.get(size);
                    } catch (Exception e) {
                        break;
                    }

                    //排除涨停的数据
                    Boolean isTrue = zhangTingBanService.zhangtingDatahis(p.getStockCode(), date);
                    isTrue=Boolean.FALSE;
                    if (!isTrue) {
                        BigDecimal yestoDayMaxVol = companyStockMinutesService.getMaxVol(date, p.getStockCode());
                        hisDayTradeVol = hisDayTradeVol.add(yestoDayMaxVol);
                        j++;
                    }
                    i++;
                    if (j == 4) {
                        if (p.getStockCode().startsWith("sh688")) {
                            hisDayTradeVol = hisDayTradeVol.divide(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP);
                        }
                        hisDayTradeVol = hisDayTradeVol.divide(new BigDecimal(5)).setScale(0, BigDecimal.ROUND_HALF_UP);
                        break;
                    }
                }
                redisUtil.set(key_avg_volume, hisDayTradeVol.toString());
            }catch (Exception e){
                log.error(">>>>>>>>> getHistoryVol error  code={} name={} dates={}",p.getStockCode(),p.getStockName(), JSONObject.toJSONString(dates));
            }
        }else {
            hisDayTradeVol = new BigDecimal(object.toString());
        }
        return hisDayTradeVol;
    }


    private BigDecimal getHistoryVol(User user, TenXunStock p, List<String> dates, BigDecimal hisDayTradeVol) {
        /** 昨天 */
        int i = 2;
        int j = 0;
        String key_avg_volume=new StringBuffer("key_avg_volume").append("_").append(user.getId()).append("_").append(p.getStockCode()).append("_").append(HolidayCopy.getToday()).toString();
        Object object=redisUtil.get(key_avg_volume);
        if(null==object) {
            try{
                for (String date : dates) {
                    int size = dates.size() - i;
                    try {
                        date = dates.get(size);
                    } catch (Exception e) {
                        break;
                    }

                    //排除涨停的数据
                    Boolean isTrue = zhangTingBanService.zhangtingDatahis(p.getStockCode(), date);
                    if (!isTrue) {
                        BigDecimal yestoDayMaxVol = companyStockMinutesService.getMaxVol(date, p.getStockCode());
                        hisDayTradeVol = hisDayTradeVol.add(yestoDayMaxVol);
                        j++;
                    }
                    i++;
                    if (j == 4) {
                        if (p.getStockCode().startsWith("sh688")) {
                            hisDayTradeVol = hisDayTradeVol.divide(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP);
                        }
                        hisDayTradeVol = hisDayTradeVol.divide(new BigDecimal(5)).setScale(0, BigDecimal.ROUND_HALF_UP);
                        break;
                    }
                }
                redisUtil.set(key_avg_volume, hisDayTradeVol.toString());
            }catch (Exception e){
                log.error(">>>>>>>>> getHistoryVol error  user id={} code={} name={} dates={}",user.getId(),p.getStockCode(),p.getStockName(),JSONObject.toJSONString(dates));
            }

        }else {
            hisDayTradeVol = new BigDecimal(object.toString());
        }
        return hisDayTradeVol;
    }

    public void sendEmail(String email, TenXunStock p) {
        String warn_key_stock=new StringBuffer("warn_key_stock_").append(email).append("_").append(p.getStockCode()).append("_").append(HolidayCopy.getToday()).toString();
        if(null!=email) {
            log.info(">>>>>>>>> send email={}",email);
            String messages = new StringBuffer("触发做T时间：").append(DateUtils.getNow()).toString();
            try{
                EmailMessage emailMessage=new EmailMessage();
                emailMessage.setCode(p.getStockCode());
                emailMessage.setName(p.getStockName() + " - " + p.getPriceChangePercentage() + "%");
                emailMessage.setEmail(email.toString());
                emailMessage.setMessage(messages);
                stockMsgSender.sendEmailMessage(JSONObject.toJSONString(emailMessage));
            }catch (Exception e){
                sendmailService.sendMailWithByZuoT(messages, p.getStockName(), p.getStockCode(), email.toString());
            }
            redisUtil.set(warn_key_stock,warn_key_stock,30);
        }
    }
}
